... und dazu etwas SoftwareArnulf SoppWie nützlich ein Umbau am Computer ist, zeigt sich natürlich erst, wenn er etwas zu tun bekommt. Das folgende Programm ist nur ein Beispiel, was man mit dem Versechzehnfacher anfangen kann. Jedes andere Maschinenprogramm, sogar BASIC-, Pascal- oder sonstige höhere Programmtexte können dort untergebracht werden (1,2), natürlich auch Datenbytes für Tabellen und dergleichen. Damit ist das leidige Himem-Thema von Tisch; nahezu jede popelige BASIC-Verschönerung (eingerückte Zeilennummern und ähnlich überflüssiges) drängelt sich dort oben und verschleißt den Platz für wirklich Wichtiges. Dieses Programm ist ein Treiber für die HRG 1b von RB-Elektronik. Er lädt selbsttätig BASIC/CMD und arbeitet anschließend im Hintergrund mit BASIC zusammen. Sein Ladebereich geht von 3000-32E4. Dahinter sind noch ein paar Bytes als Datenpuffer reserviert. Um beim Laden des Treibers nicht den DOS-Fehler "Ladeversuch auf ROM-Speicherplatz" serviert zu bekommen, muß dort natürlich RAM vorhanden sein. Der User gibt deshalb zuvor auf den Port F0 die Nummer eines Steckplatzes auf dem Versechzehnfacher aus, wo ein statisches RAM sitzt. Unter H-DOS geht das mit OUT F0,xx (7). Ansonsten kann man zunächst BASIC starten und dann OUT 240,xx anschließend CMD"S=HRG" eingeben (sofern man dieses Programm unter dem Namen HRG/CMD auf Disk stehen hat). A propos H-DOS: Da der Befehl CMD > (mehr darüber weiter unten) das Parallel-RAM auf der CPU-Platine benutzt, müssen Besitzer des EG 64 MBA mit diesem DOS zuvor INI.N eingeben. Damit werden zwar die interessantesten Features von H-DOS disabled, aber noch immer hat der User alle G-DOS-Möglichkeiten und noch ein bißchen mehr. Auf allen Maschinen, mit denen Banking nicht möglich ist, funktioniert dieser Befehl ganz einfach nicht, ohne aber Schaden anzurichten oder zu einem Fehler zu führen. Der Treiber stellt eine Reihe von Kommandos an die HRG zur Verfügung. Sie alle beginnen mit CMD (1). Um dem Interpreter anzuzeigen, daß es sich nicht um das gewohnte CMD handelt, folgt unmittelbar darauf nicht eine Variable oder ein Ausdruck zwischen Gänsefüßchen, sondern ein zweites BASIC-Token: CMD + : HRG einschalten CMD - : HRG ausschalten CMD CLS : HRG-Speicher löschen CMD SET : einen HRG-Punkt setzen CMD RESET : einen HRG-Punkt löschen CMD POINT : testen, ob ein HRG-Punkt gesetzt ist CMD < : HRG invertieren (weiß <-> schwarz) CMD LPRINT : HRG-Inhalt auf Drucker ausgeben (Hardcopy) CMD ASC : ASCII-Bildschirm in Hex anzeigen, bis neue Taste gedrückt CMD > : Bildschirm gegen Pufferinhalt austauschen CMD LINE : noch nicht programmiert, ergibt aber keinen Fehler Nach der üblichen BASIC-Syntax können CMD und das zweite Token direkt oder durch Blank getrennt hintereinander stehen. Diese Befehle können im Direktmodus und als Bestandteil eines Programms eingegeben werden. Die drei erstgenannten HRG-Befehle bedürfen keiner näheren Erläuterung. CMD SET, CMD RESET und CMD POINT haben eine ganz ähnliche Syntax wie die gewohnten Befehle zur Ansteuerung der Genie-Pixelgraphik. Im Argument sind im Unterschied dazu jedoch Koordinaten im Bereich 0-383 für X und 0-191 für Y zulässig, entsprechend der feineren HRG-Matrix. Die Koordinaten können wie in Level 2 oder Disk-BASIC auch durch Variable dargestellt werden. CMD < macht aus jedem Punkt im HRG-Speicher sein Komplement. Gesetzte Punkte werden dunkel, nicht gesetzte werden eingeschaltet. Es entsteht eine negative Darstellung. Der normale ASCII-Bildschirm bleibt hiervon unberührt. Bei einem Bildschirmausdruck der HRG mit CMD LPRINT wird der Drucker zunächst in den Einschaltzustand versetzt (Reset aller Druckparameter). Danach wird der linke Rand auf die 9. Stelle gesetzt, um das Bild zu zentrieren. Der Zeilenabstand wird mit 6/72" so eingestellt, daß die Druckzeilen lückenlos untereinander stehen. Nach getaner Arbeit werden diese Steuercodes alle wieder gelöscht; der Drucker ist wieder im Einschaltzustand. Diese Codes gelten für den Star Gemini-10X. Für andere Printer müssen sie entsprechend geändert werden. Von den vergleichbaren Epson-Typen ist mir bekannt, daß für die Randeinstellung lediglich in ESC M 09 aus dem "M" ein "1" gemacht zu werden braucht. Die übrigen Codes sind identisch. Der Befehl CMD ASC ist für vielerlei Verwendungen interessant. Mit ihm hat der Programmierer sozusagen immer eine ASCII-Tabelle auf dem Bildschirm. Die ASCII-Zeichen werden als zweistellige Hexzahlen dargestellt (4). So werden gleiche Zeichen mit verschiedenen Codes unterscheidbar, um nur eine Anwendung zu nennen: Die beiden Blanks mit den Codes 32 und 128 sowie die Graphikblocks 128-191 und 192-255 sind als Hexzahlen eindeutig zu identifizieren. Bei der Ausführung von CMD ASC werden die 32er Blanks übrigens nicht mit umgewandelt, sondern als Leerzeichen belassen, um den Bildschirm übersichtlich zu halten. Dabei wird der normale ASCII-Bildschirm natürlich gelöscht, sonst würde er stören. Der Treiber rettet ihn in den HRG-Speicher, so daß -er nach dem Druck auf irgendeine Taste wieder restauriert werden kann. Ein besonderer Puffer im RAM ist dafür nicht erforderlich. Nach diesem Schema geht auch der Befehl CMD > vor. Zunächst wird der Bildschirm in die HRG gerettet. Von ihr sind nämlich nur 6 Bits pro Byte sichtbar, die beiden höchstwertigen Bits sind unbenutzt und können den Bildschirm aufnehmen. Dabei wird der sichtbare Inhalt des HRG-Speichers nicht beeinträchtigt. Alle Graphiken bleiben also erhalten. Im weiteren Verlauf der Ausführung dieses Befehls wird nun der Inhalt der HRG, also Graphik und ASCII, in einen Puffer gerettet, und der Inhalt dieses Puffers geht dafür in die HRG. Die beiden höchstwertigen Bits des neuen HRG-Inhalts werden in den ASCII-Bildschirm übertragen. Es ist demnach ein Austausch Bildschirm gegen Puffer. In diesem Treiber liegt der Puffer im Adreßbereich ab 0000. Das ist natürlich nur mit dem EG 64 MBA oder einem anderen Banker realisierbar. Entsprechende Änderungen, um stattdessen das gute alte Himem dafür zu benutzen, sind kein Problem. Der Befehl CMD LINE soll eines fernen Tages, wenn der Autor mal wieder Lust hat, an dem Treiber weiterzuarbeiten, Linien, Rechtecke usw. ziehen. Der Leser möge mir nachsehen, daß die Computerei mein Hobby ist, bei dem ich gnadenlos dem Lustprinzip folge (6). An diesem fernen Tage werden wohl noch ein paar andere Modifikationen folgen, die es ermöglichen. den HRG-Treiber fest in ein EPROM zu brennen. Das ist mit dieser Version nicht möglich, denn das Programm vollzieht Schreibzugriffe in seinem eigenen Adreßraum. Dazu gehören z. B. die Datenpuffer an seinem Ende, aber auch variable Sprungdistanzen mitten im Programm (Selbstmodifikation). Der Vorteil dieser Variante ist freilich, daß der Treiber mit den Bedürfnissen jederzeit mitwachsen kann. Immerhin sind noch eineinviertel kB frei! Auf die Programmlogik möchte ich an dieser Stelle nicht eingehen. Die siebeneinhalb Seiten Listing wären halbwegs erschöpfend wohl nicht mit weniger als 15 Seiten Test erklärbar. Insbesondere diejenigen Features, die kein anderer mir bekannter HRG-Treiber zur Verfügung stellt, würden einige Seiten füllen: Z. B. die Umwandlung des ASCII-Bildschirms in die Hexdarstellung und das Puffern desselben im HRG-Speicher. Der Maschinensprache-Freak mag sich dabei amüsieren, sich in dem sehr ausführlich kommentierten Listing selber zurechtzufinden. Zu diesem Thema sind an gleicher Stelle auch bereits ein paar Beiträge erschienen, die die Arbeit deutlich erleichtern werden (5 u.a.). Nur einige wenige Kommentare, ohne die sich sogar der Autor kaum noch im Programm zurechtfindet, sollen angefügt sein: In BASIC/CMD steht nach dem Laden (also noch vor dem Ansprung!) an 67DD der CMD-Vektor (JP 57FF). Er wird durch JP cmd (3074) ersetzt. Andere Treiber benutzen kein bereits vorhandenes Token und verlangsamen damit den ganzen Computer: es muß bei jeder Eingabe geprüft werden, ob ein vorangestelltes Doppelkreuz o. dergl. ein Syntaxfehler oder die Einleitung eines HRG-Befehls ist. An der Stelle 64F3 wird HL als Zeiger auf das BASIC-Helle geladen. Mit der Änderung des LSB von 5C auf 5E werden die beiden ersten Codes, die den Bildschirm löschen, übergangen. So bleibt die oberste Titelzeile erhalten, die beim Label hello steht. Beim späteren Programmablauf wird der Treiber nur dann angesprungen, wenn das CMD-Token angetroffen wurde. Nun prüft er, was folgt. In Disk-BASIC ist es immer ein Anführungszeichen oder ein Variablenname. Diese Zeichen liegen im Bereich bis 7F. Der Vergleich mit 80 beim Label cmd gibt deshalb Aufschluß, ob zur Ansteuerung der HRG ein weiteres Token folgt. Falls nein, geht es in der alten CMD-Routine weiter, falls ja, kommt der Treiber jetzt so richtig in Fahrt. Anwender, die mit EDTASM/CMD oder ASM/CMD arbeiten. müssen auf die für diese Assembler zulässige Syntax achten; Labels dürfen höchstens 6 Zeichen lang sein, Kleinbuchstaben sind nur in den Kommentaren erlaubt, DB, DW und DM müssen als DEFB, DEFW und DEFM ausgeschrieben werden. Bei diesen Statements dürfen auch nicht mehrere Argumente in derselben Zeile stehen, schon gar nicht DEFM und DEFB gemischt. Je eine eigene Zeile muß dafür eingerichtet werden. Dieser HRG-Treiber ist, wie gesagt, lediglich eine Demonstration dafür, was mit Helmut Bernhardts Versechzehnfacher so alles anzufangen ist. Die Platine funktioniert selbstverständlich ohne HRG, auch ohne DOS ebenso gut wie mit. Vielleicht fällt einem von euch für eins der nächsten Infos eine sinnvolle Verwendung für Level 2 ein? Literatur: 1) "PUT TO - ein neuer BASIC-Befehl", 4/1984 2) "Bank Selection mit dem Genie I", 5/1985 3) "Neuer DOS-Befehl: OUT port#,xx,yy,...", 11/1984 4) "VIDHEX - Hexanzeige des Bildschirms mit der HRG", 9/1985 5) "Die HRG 1b programmieren", 11/1984 (alle von A. Sopp im Club-Info des Genie/TRS80-User-Club Bremerhaven, Ausgabe jeweils angegeben). 6) R. Goscinny, M. Uderzo: "Asterix und der Kupferkessel", Dargaud S. A. 1969 00001 ; 00002 ; 00003 ; BASIC-Treiber für die HRG 1b von RB-Elektronik 00004 ; 00005 ; Demo-Programm zum Speicher-Versechzehnfacher 00006 ; im Adreßraum 3000-370F von Helmut Bernhardt 00007 ; 00008 ; (C) Arnulf Sopp 00009 ; 00010 ; 00011 3000 00012 ORG 3000h ;im Sonder-ROM-Bereich 00013 00014 ;DOS-Eingabepuffer retten 3000 11E432 00015 finit LD DE,cmdbuf ;Puffer für Aufrufbefehl 3003 014800 00016 LD BC,0048h ;ca. Lng. DOS-Eing.-puff. 3006 E5 00017 PUSH HL ;Aufrufbefehl retten, 3007 D5 00018 PUSH DE ;weil 4419 den Puffer- 3008 C5 00019 PUSH BC ;Inhalt verändert 3009 EDB0 00020 LDIR ;zwischenspeichern 00021 00022 ;Initialisierungen in BASIC/CMD 3008 212C30 00023 LD HL,command ;BASIC-Ladekommando 300E CD1944 00024 CALL 4419h ;BASIC/CMD laden 3011 217430 00025 LD HL,cmd ;neuer CMD-Vektor 3014 22DD67 00026 LD (67ddh),HL ;in BASIC/CMD laden 3017 3E5E 00027 LD A,5eh ;LSB des BASIC-Logo 3019 32F464 00028 LD (64f4h),A ;CLS verhindern 301C 213830 00029 LD HL,hello ;HRG-Logo 301F CD6744 00030 CALL 4467h ;anzeigen 3022 C1 00031 POP BC ;Länge Eingabepuffer 3023 E1 00032 POP HL ;Aufrufbefehl 3024 D1 00033 POP DE ;Adresse Eingabepuffer 3025 D5 00034 PUSH DE ;brauchen wir gleich 3026 EDB0 00035 LDIR ;Befehl restaurieren 3028 E1 00036 POP HL ;Befehlserweit. oder CR 3029 C3BE66 00037 JP 66beh ;BASIC-Kaltstart 00038 00039 ;DOS-Befehl, um BASIC in den Speicher zu laden 302C 6C 00040 command DM 'load,basic/cmd',0dh 00041 00042 ;neue 1. Zeile des BASIC-Hello 3038 1C 00043 hello DM 1ch,1fh,'H R G 1 b - Utility von ' 3056 54 00044 DM 'The HACKTORY Arnulf Sopp für',Oah,0dh 00045 00046 ;BASIC-Erweiterung für HR-Graphikbefehle 3074 FE80 00047 cmd CP 80h ;Graphik-CMD-Befehl? 3076 DAFF57 00048 JP C,57ffh ;norm. weiter, falls nein 00049 00050 ;Es ist ein HRG-Befehl. Erkennen und ausführen: 3079 FED4 00051 CP 0d4h ;Bildschirm austauschen? 307B 2029 00052 JR NZ,CLS ;falls nein 00053 00054 ;CMD >: Bildschirm gegen Pufferinhalt austauschen 307D E5 00055 PUSH HL ;Befehlszeiger 307E CD5332 00056 CALL vidsav ;Bildschirm retten 3081 F3 00057 DI ;bloß keine Störungen! 3082 3E08 00058 LD A,8 ;RD RAM 0000-2FFF 3084 D3DF 00059 OUT (0dfh),A ;auf Banking-Port ausg. 3086 3C 00060 INC A ;WR RAM 0000-2FFF 3087 D3DF 00061 OUT (0dfh),A ;dto. 3089 65 00062 LD H,L ;HL <- 0000, Pufferadr. 308A 55 00063 LD D,L ;DE <- 00xx, HRG-Adresse 3088 50 00064 LD E,L ;DE <- 0000 308C 0E30 00065 LD C,30h ;Konst. HRG-MSB 308E CD4B32 00066 swaplop CALL HRGadr ;HRG-Stelle adressieren 3091 DB04 00067 IN A,(4) ;HRG-Byte laden 3093 46 00068 LD B,(HL) ;Pufferbyte holen 3094 77 00069 LD (HL),A ;HRG-Byte puffern 3095 78 00070 LD A.B ;Pufferbyte 3096 0305 00071 OUT (5),A ;auf HRG ausgeben 3098 23 00072 INC HL ;Pufferzeiger erhöhen 3099 7A 00073 LD A,D ;überprüfen, ob 309A 89 00074 CP C ;HkG-Bereich überschr.? 3098 38F1 00075 JR C,swaplop ;falls nein 309D DBDF 00076 IN A,(0dfh) ;Banks rücksetzen 309F FBI 00077 EI ;INTs wieder zulassen 30A0 CD5532 00078 CALL savrest ;Bildsch. restaurieren 30A3 E1 00079 POP HL ;Befehlszeiger 30A4 1831 00080 JR exit1 ;fertig 00081 00082 ;CMD CLS: HRG-Speicher löschen 30A6 FE84 00083 CLS CP 84h ;CLS? 30A8 2004 00084 JR NZ,INV ;falls nein 30AA 1E00 00085 clear LD E,0 ;Flag für HRG-CLS 30AC 1806 00086 JR clsinv ;dort weiter 00087 00088 ;CMD <: HRG invertieren (positiv -> negativ) 30AE FED6 00089 INV CP Od6h ;invertieren? 3080 2027 00090 JR NZ,LINE ;falls nein 3082 1EFF 00091 LD E,0ffh ;Flag für Inversion 3084 010330 00092 clsinv LD BC,3003h ;8 = MSB 12kB, C = Port 3 3087 C5 00093 msloop PUSH BC ;retten 30B8 05 00094 DEC ;B um 1 zu hoch 30B9 ED41 00095 OUT (C),B ;MSB HRG-Adresse 3088 0600 00096 LD B,0 ;B <- 0 für HRG-LSB 30BD 0D 00097 DEC C ;Port 2 für LSB 308E ED41 00098 lsloop OUT (C),B ;LSB HRG-Adresse 3000 DB04 00099 IN A,(4) ;HRG-Byte holen 30C2 F5 00100 PUSH AF ;retten 30C3 E6C0 00101 AND 0c0h ;obere Bits isolieren 3005 57 00102 LD D,A ;und retten 3006 F1 00103 POP AF ;HRG-Byte 3007 2F 00104 CPL ;invertieren 3008 E63F 00105 AND 3fh ;obere Bits ausmaskieren 30CA CB7B 00106 BIT 7,E ;CLS oder INV? 30CC 2001 00107 JR NZ,outa ;falls INV 30CE AF 00108 XOR A ;sonst löschen 30CF 82 00109 outa OR D ;obere Bits hinzufügen 3000 0305 00110 OUT (5),A ;Blank od. Kompl. ausgeb. 3002 10EA 00111 DJNZ lsloop ;LSB: 00, FF, FE ... 01 3004 C1 00112 POF BC ;MSB und Port für MSB 3005 10E0 00113 DJNZ msloop ;MSB-1: 2F ... 00 00114 00115 ;Rückkehr für mehrere Unterprogramme 3007 23 00116 exit1 INC HL ;Befehlszeiger nachst. 3008 C9 00117 RET ;erledigt 00118 00119 ;CMD LINE: (bisher nicht programmiert) 3009 FE9C 00120 LINE CP 9ch ;LINE? 3008 28FA 00121 JR Z,exit1 ;vorl. nicht implement. 00122 00123 ;CMD 4: HRG-Speicher in den Bildschirm einblenden 3000 FECD 00124 CP Ocdh ;HRG einschalten? 30DF 2004 00125 JR NZ,HRGoff ;falls nein 30E1 0301 00126 OUT (1),A ;einschalten 30E3 18F2 00127 JR exit1 ;fertig 00128 00129 ;CMD - HRG-Speicher aus dem Bildschirm ausblenden 30E5 FECE 00130 HRGoff CP Oceh ;HRG ausschalten? 30E7 2004 00131 JR NZ,LPRINT ;falls nein 30E9 0300 00132 OUT (0),A ;ausschalten 30EB 18EA 00133 JR exit1 ;fertig 30ED FEAF 00134 30EF 2066 00135 ;CMD LPRINT: Hardcopy des HRG-Speichers 00136 LPRINT CP 0afh ;LPRINT (Hardcopy)? 00137 JR NZ,ASC ;falls nein 00138 00139 ;LPRINT; Drucker initial.: Reset, 6/72" Zeilenabstand 30F1 E5 00140 PUSH HL ;Befehlszeiger retten 30F2 210632 00141 LD HL,prestor+1 ;Druckerinitialisierung 30F5 0609 00142 LD B,9 ;mit 9 Codes 30F7 CDFC31 00143 CALL lprint ;Ausgabe auf Drucker 00144 00145 ;HRG-Zeiger laden, 16 (Doppel-)Zeilen vorbereiten 30FA 50 00146 LD D,B ;DE <- 00xx 30FB 58 00147 LD E,B ;DE <- 0000, Start HRG 30FC 010610 00148 LD BC,1006h ;16 Zeilen, Konst. 6 00149 00150 ;1 Doppelzeile zu je 6 Dotzeilen drucken 30FF C5 00151 scrnlop PUSH BC ;Zähler retten 3100 D5 00152 PUSH DE ;dto. HRG-Zeiger 3101 0602 00153 LD B,2 ;2 Halbzeilen/Zeile 3103 C5 00154 linelop PUSH BC ;wird verändert 3104 D5 00155 PUSH DE ;dto. HRG-Zeiger 3105 21DF32 00156 LD HL,lninit ;Druckerinit. für 1 Zeile 310B 0605 00157 LD B,5 ;mit 5 Codes 310A CDFC31 00158 CALL lprint ;Ausgabe 3100 21E432 00159 LD HL,buffer ;Puffer für Druckercodes 3110 0640 00160 LD B,40h ;64 Bytes/Zeile 00161 00162 ;1 Halbzeile drucken 3112 C5 00163 hlinlop PUSH BC ;Zähler retten 3113 D5 00164 PUSH DE ;dto. HRG-Zeiger 3114 78 00165 LD A,E ;LSB des HRG-Zeigers 3115 D302 00166 OUT (2),A ;auf HRG ausgeben 3117 41 00167 LD B,C ;6 Bytes senkrecht 00168 00169 :1 Byte drucken 3118 C5 00170 bytelop PUSH BC ;wird verändert 3119 7A 00171 LD A,D ;MSB des HRG-Zeigers 311A 0303 00172 OUT (3);A ;auf HRG ausgeben 311C DB04 00173 IN A,(4) ;Dotzeile aus HRG 311E 41 00174 LD B,C ;6 Dots/Stelle 311F E5 00175 PUSH HL ;retten 00176 00177 ;6mal 1 Bit errechnen 3120 0F 00178 bitlop RRCA ;Cy <- HRG-Bit 3121 CB16 00179 RL (HL) ;nächstes Pufferbit <- Cy 3123 CBB6 00180 RES 6,(HL) ;nur untere Bits 3125 23 00181 INC HL ;nächstes Pufferbyte 3126 10F8 00182 DJNZ bitlop ;bis 6 Dots gepuffert 00183 00184 ;6 Bits fertig - 6 Bytes vervollständigen 3128 14 00185 INC D ;MSB auf nächste Dotzeile 3129 14 00186 INC D ;= um 1 kB erhöhen) 312A 14 00187 INC D 3120 14 00188 INC D 312C E1 00189 POP HL ;Pufferzeiger 312D C1 00190 POP BC ;Zähler 312E 10E8 00191 DJNZ bytelop ;bis 1 Stelle im Puffer 00192 00193 ;6 Bytes ausdrucken und weiter mit Halbzeile 3130 E5 00194 PUSH HL ;wird verändert 3131 41 00195 LD B.0 ;6 Dotspalten 3132 CDFC31 00196 CALL lprint ;ausgeben 3135 E1 00197 POP HL ;Pufferzeiger 3136 D1 00198 POP DE ;alter HRG-Zeiger 3137 13 00199 INC DE ;nächstes HRG-Byte 3138 C1 00200 POP BC ;Halbzeilenzähler 3139 1007 00201 DJNZ hlinlop ;bis 1 Halbzeile gedruckt 00202 00203 ;Ganzzeile vervollständigen 3138 D1 00204 POP DE ;HRG-Zeiger 31330 3E18 00205 LD A.18h ;6 Dotzeilen (6 kB) 313E B2 00206 ADD A,D ;zum MSB addieren 313F 57 00207 LD D,A ;neu laden 3140 C1 00208 POP BC ;Zeilenzähler 3141 1000 00209 DJNZ linelop ;bis 12 Dotzeilen gedr. 00210 00211 ;weiter mit der nächsten Zeile 3143 D1 00212 POP DE ;HRG-Zeiger 3144 214000 00213 LD HL,0040h ;Summand 64 3147 19 00214 ADD HL,DE ;LSB um eine Zeile erhöh. 3148 EB 00215 EX DE,HL ;Zeiger <- neuer Wert 3149 C1 00216 POP BC ;Zeilenzähler 314A 1083 00217 DJNZ scrnlop ;bis Bildschirm gedruckt 00218 00219 ;fertig - Drucker wieder in Normalstatus versetzen 314C 210532 00220 LD HL,prestor ;Dr. reinitialisieren 314F 0604 00221 LD B,4 ;mit 4 Codes 3151 CDFC31 00222 CALL lprint ;Ausgabe 3154 E1 00223 POP HL ;Befehlszeiger 3155 23 00224 exit2 INC HL ;Befehlszeiger aktualis. 3156 C9 00225 RET ;und raus 00226 00227 ;CMD ASC: Bildschirmanzeige in Hex umwandeln 3157 FEF6 00228 ASC CP 0f6h ;ASC? 3159 2026 00229 JR NZ,PSR ;falls nein 3158 ES 00230 PUSH HL ;Befehlszeiger retten 315C CDAA30 00231 CALL clear ;HRG-Speicher löschen 00232 00233 ;Bildschirm retten 315E D301 00234 OUT (1),A ;HRG einschalten 3161 CD5332 00235 CALL vidsav ;Bildschirm retten 00236 00237 ;Bildschirm von ASCII- in Hexanzeige ändern 3164 263C 00238 LD H,3ch ;Bildschirmanfang 3166 E5 00239 hexdisp PUSH HL ;dto. 3167 4E 00240 LD C,(HL) ;Bildschirmzeichen 3168 3E20 00241 LD A,' ' ;Blank 316A B9 00242 CP C ;Blank? (nicht verändern) 316B 77 00243 LD (HL),A ;diese Stelle löschen 316C C40832 00244 CALL NZ,byte ;kein Bl., 1 Byte umwand. 00245 00246 ;Zeichen umgewandelt oder Blank überspr.; nächst. Zeichen 316E E1 00247 POP HL ;Bildschirmzeiger 3170 23 00248 INC HL ;nächste Stelle 3171 C874 00249 BIT 6,H ;Bildsch. überschritten? 3173 28F1 00250 JR Z,hexdisp ;nein, nächstes Byte 3175 CD4900 00251 00252 ;Nach Anzeige auf Tastendruck warten, dann Bildschirm restaur. 00253 CALL 0049h ;auf Taste warten 3178 4D 00254 LD C,L ;C <- 00, Bildsch. rest. 3179 CD5532 00255 CALL savrest ;UP abarbeiten 317C 0300 00256 OUT (0),A ;HRG ausschalten 317E E1 00257 POP HL ;Befehlszeiger 317F 1804 00258 JR exit2 ;und raus 00259 00260 ;CMD POINT, CMD SET oder CMD RESET 3181 CDA131 00261 PSR CALL argum ;Ausdruck auswerten 3184 FE82 00262 CP 82h ;RESET? 3186 2908 00263 JR Z,reset 3188 FE83 00264 CP 83h ;SET? 318A 280A 00265 JR Z,set 318C FEC6 00266 CP 0c6h ;POINT? 318E 2800 00267 JR Z,point 3190 1808 00268 JR PSRexit ;falls Fehler 00269 00270 ;CMD RESET 3192 78 00271 reset LD A,B ;HRG-Byte laden 3193 A9 00272 XOR C ;Bit rücksetzen 3194 1802 00273 JR out ;Ausgabe und zurück 00274 00275 ;CMD SET 3196 78 00276 set LD A,8 3197 81 00277 OR C ;Bit setzen 3198 D305 00278 out OUT (5),A ;auf HRG ausgeben 00279 00280 ;gemeinsamer Rücksprung für CMD RESET und SET 319A C38C01 00281 PSRexit JP 018ch ;-> BASIC 00282 00283 ;CMD POINT - Flag für Dot ja oder nein in (CMDBUF) 319D 78 00284 point LD A,B 319E C39201 00285 JP 0192h ;weiter wie Level 2 00286 00287 ;CMD POINT, SET oder RESET - Argument ausrechnen 3141 F5 00288 argum PUSH AF ;Token retten 3142 23 00289 INC HL ;Befehlszeiger nachstell. 3143 CF 00290 RST 08h ;auf '1' prüfen 3144 28 00291 DB '1' ;sonst Syntaxfehler 3145 CD461E 00292 CALL 1e46h ;DE <- Abszisse 3148 E5 00293 PUSH HL ;Befehlszeiger retten 3149 217F01 00294 LD HL,017fh ;Maximalwert für X 31AC DF 00295 RST 18h ;Vergleich mit Eingabe 314D E1 00296 fcterr POP HL ;Befehlszeiger restaur. 314E 04441E 00297 JP C,1e4ah ;Funktionsf., falls mehr 3181 D5 00298 PUSH DE ;Abszisse retten 3182 CF 00299 RST 08h ;auf ',' prüfen 3183 2C 00300 DB ',' ;sonst Syntaxfehler 3184 CD461E 00301 CALL 1e46h ;DE <- Ordinate 3187 E5 00302 PUSH HL ;Befehlszeiger retten 3188 218F00 00303 LD HL,00bfh ;Maximalwert für Y 3188 DF 00304 RST 18h ;Vergleich mit Eingabe 31BC E1 00305 POP HL ;Befehlszeiger restaur. 3I80 38EE 00306 JR C,fcterr ;Fehler, falls höher 318e 22E432 00307 LD (cmdbuf),HL ;Befehlszeiger retten 31C2 EB 00308 EX DE,HL ;zur Vereinf. d. Folgend. 31C3 E3 00309 EX (SP),HL ;X- <-> Y-Koordinate 3104 3E06 00310 LD A,06h ;wegen 6 Dots/Byte 3106 CD7944 00311 CALL 4479h ;HL/A=HL Rest A 31C9 D1 00312 POP DE ;Ordinate holen 31CA F5 00313 PUSH AF ;Bit-Nr. retten 3108 E5 00314 PUSH HL ;dto. X-Koordinate 31CC EB 00315 EX DE,HL ;HL <- Y-Koordinate 31CD 3E0C 00316 LD A,0ch ;wegen 12 Dotzeil./Stelle 31CF CD7944 00317 CALL 4479h ;HL/A=HL Rest A 3102 F5 00318 PUSH AF ;Rest retten 3103 3E40 00319 LD A,40h ;64 Stellen/Zeile 3105 CD7644 00320 CALL 4476h ;A*HL=AHL 3108 44 00321 LD B,H ;HL nach BC retten 31D9 4D 00322 LD C,L 31D4 F1 00323 POP AF ;obigen Rest holen 3108 210004 00324 LD HL,0400h ;Faktor 1kB 310E CD7644 00325 CALL 4476h ;A*HL=AHL 31E1 09 00326 ADD HL,BC ;Zwischensumme 31E2 C1 00327 POP BC ;X-Koordinate 31E3 09 00328 ADD HL,BC ;Endsumme = HRG-Adresse 31E4 7D 00329 LD A,L ;LSB 31E5 0302 00330 OUT (2),A ;auf HRG ausgeben 31E7 7C 00331 LD A,H ;MSB 31E8 D303 00332 OUT (03h),A ;dto. 31EA C1 00333 POP BC ;B <- Bit-Nr. 310B 04 00334 INC B ;B <- mindestens 1 31EC 3E80 00335 LD A,80h ;Anfangswert für A 31EE 07 00336 doublop RLCA ;fortgesetzt A*2 31EF 10FD 00337 DJNZ doublop ;bis richtiges Bit in A 31F1 E63F 00338 AND 3fh ;nur die ersten 6 Bits 31F3 4F 00339 LD C,A ;Akku retten 31F4 DB04 00340 IN A,(4) ;Inh. HRG-Speicherstelle 31F6 47 00341 LD B,A ;HRG-Byte retten 31F7 F1 00342 POP AF ;Token restaurieren 31F8 24E432 00343 LD HL,(cmdbuf) ;Befehlszeiger restaur. 31FB C9 00344 RET ;erledigt 00345 00346 ;Zeichenfolge ab (HL) auf Drucker ausgeben 31FC CDD105 00347 lprint CALL 05d1h ;Drucker bereit? 31FF 20FB 00348 JR NZ,lprint ;falls nein 3201 7E 00349 LD A,(HL) ;zu druckendes Zeichen 3202 D3FD 00350 OUT (0fdh),A ;auf Drucker ausgeben 3204 23 00351 INC HL ;nächste Stelle 3205 10F5 00352 DJNZ lprint ;nächstes Zeichen 3207 C9 00353 RET ;zurück 00354 00355 ;UP Hexanzeige: 1 Byte ändern 320E 7C 00356 byte LD A,H ;MSB der Videoadresse 3209 E603 00357 AND 03 ;Adr. Vid. -> Adr. HRG 320B 57 00358 LD D,A ;neues MSB 320C SD 00359 LD E,L ;HRG-MSB wie Video-MSB 320D 79 00360 LD A,C ;Videozeichen 320E E6F0 00361 AND 0f0h ;oberes Nibble 3210 0F 00362 RRCA ;ins untere schieben 3211 0F 00363 RRCA 3212 0F 00364 RRCA 3213 0F 00365 RRCA 3214 21B032 00366 LD HL,chrtab-5 ;vor Tab. f. Hexzeich, 3217 E5 00367 PUSH HL ;brauchen wir noch 3218 CD1F32 00368 CALL nibble ;oberes Nibble anzeigen 321B 79 00369 LD A,C ;alter Code 321C E60F 00370 AND 0fh ;unteres Nibble 321E E1 00371 POP HL ;Tabellenzeiger 00372 00373 ;einzelnes Halbbyte in die HRG laden 321F 47 00374 nibble LD B,A ;als Zähler i. d. Tabelle 3220 3A3932 00375 LD A,(displc) ;Sprungdistanz 3223 EE02 00376 XOR output-displc-1 ;umschalten 3225 323932 00377 LD (displc),A ;neu laden 3228 04 00378 INC B ;wegen DE = Tabelle -5 3229 23 00379 seekchr INC HL ;Zeiger nachstellen 322A 23 00380 INC HL ;über 5 Stellen, weil 322B 23 00381 INC HL ;5 Codes pro Zeichen 322C 23 00382 INC HL 322D 23 00383 INC HL 322E 10F9 00384 DJNZ seekchr ;bis Code gefunden 3230 0605 00385 LD B,5 ;5 Dotzeilen pro Zeichen 3232 C5 00386 nibloop PUSH BC ;Zähler retten 3233 CD4B32 00387 CALL HRGadr ;HRG-Stelle adressieren 3236 18 00388 DEC DE ;HRG-Zeiger korrigieren 3237 7E 00389 LD A,(HL) ;Dotzeile laden 3238 1B00 00390 JR $+2 ;variable Sprungdistanz 3239 00391 displc EQU $-1 ;hier Distanzbyte 3236 07 00392 RLCA ;lower Nibble verschieben 3238 07 00393 RLCA ;um 2 Dots 323C 4F 00394 output LD C,A ;Dotzeile retten 323D DB04 00395 IN A,(4) ;HRG-Byte mit Videocode 323F B1 00396 OR C ;mit Dotzeile verknüpfen 3240 D305 00397 OUT (5),A ;Dotzeile in HFG laden 3242 14 00398 INC D ;im MSB um 1 kB erhöhen 3243 14 00399 INC D ;für nächste Dotzeile 3244 14 00400 INC D 3245 14 00401 INC D 3246 23 00402 INC HL ;nächster Code für Ziffer 3248 10E8 00404 DJNZ nibloop ;bis Nibble angezeigt 324A C9 00405 RET ;zurück 3247 C1 00403 POP BC ;Zähler restaurieren 3248 10E8 00404 DJNZ nibloop ;bis Nibble angezeigt 324A C9 00405 RET ;zurück 00406 00407 ;UP, um die HRG-Adresse auszugeben 324B 7B 00408 HRGadr LD A,E ;LSB der HRG-Adresse 324C D302 00409 OUT (2),A ;auf Port ausgeben 324E 7A 00410 LD A,D ;MSB 324F D303 00411 OUT (3),A ;dto. 3251 13 00412 INC DE ;nächste HRG-Stelle 3252 C9 00413 RET 00414 00415 ;UP, um Bildschirm zu retten oder zu restaurieren 3253 0EC0 00416 vidsav LD C,0c0h ;Konstante 3255 210030 00417 savrest LD HL,3c00h ;Bildschirmadresse 3258 55 00418 LD D,L ;DE <- 00xx, HRG-Adresse 3259 50 00419 LD E,L ;DE <- 0000 325A 0604 00420 vidsav1 LD B,4 ;4*2 Bits/Byte 325C CD4B32 00421 vidsav2 CALL HRGadr ;HRG-Stelle adressieren 325F CB79 00422 BIT 7,C ;Bildschirm retten? 3261 2812 00423 JR Z,restor ;falls nein 3263 7E 00424 LD A,(HL) ;Bildschirmzeichen 3264 A1 00425 AND C ;nur oberste 2 Bits 3265 C5 00426 PUSH BC ;C retten 3266 4F 00427 LD C,A ;Akku retten 3267 DB04 00428 IN A,(4) ;HRG-Byte holen 3269 E63F 00429 AND 3fh ;oberste Bits ausmaskier. 326B B1 00430 OR C ;Videobits zufügen 326C C1 00431 POP BC ;C restaurieren 326D D305 00432 OUT (5),A ;auf HRG ausgeben 326F CB06 00433 RLC (HL) ;Zeichen 2 Bits aufrücken 3271 CB06 00434 RLC (HL) 3273 1808 00435 JR gosave ;dort weiter 3275 OB04 00436 restor IN A,(4) ;HFG-Byte holen 3277 07 00437 RLCA ;2 oberste Bits 3278 CB16 00438 RL (HL) ;in den Bildsch. laden 327A 07 00439 RLCA 327B CB16 00440 RL (HL) 327D 1000 00441 gosave DJNZ vidsav2 ;bis 1 Byte fertig 327F 23 00442 INC HL ;nächste Videostelle 3280 CB74 00443 BIT 6,H ;Bildsch. überschritten? 3282 C0 00444 RET NZ ;falls ja 3283 1805 00445 JR vidsav1 ;weiter, falls nein 00446 00447 ;Codetabelle für HRG-Zeichensatz 3285 02 0044B chrtab DB 2,5,5,5,2 ;0 328A 04 00449 DB 4,6,5,4,4 ;1 328F 03 00450 DB 3,4,2,1,7 ;2 3294 07 00451 DB 7,4,2,4,7 ;3 3299 04 00452 DB 4,5,7,4,4 ;4 329E 07 00453 DB 7,1,3,4,3 :5 3243 06 00454 DB 6,1,7,5,2 ;6 3248 07 00455 DB 7,4,2,1,1 ;7 32AD 02 00456 DB 2,5,2,5,2 :8 32B2 02 00457 DB 2,5,7,2,1 ;9 32B7 02 00458 OB 2,5,7,5,5 ;A 32BC 03 00459 DB 3,5,3,5,3 ;B 3201 06 00460 DB 6,1,1,1,6 ;C 32C6 03 00461 DB 3,5,5,5,3 ;D 32CB 07 00462 OB 7,1,3,1,7 ;E 32D0 07 00463 DB 7,1,3,1,1 ;F 00464 00465 ;versch. Druckercodes, Puffer für Dotspalten usw. 32D5 0D 00466 prestor DB 0dh,0dh,1bh,'§' ;Drucker reinitialisieren 32D9 1B 00467 DB 1bh,'M',09h ;li. Rand auf 9. Stelle 32DC 18 00468 DB 1bh,'A',06h ;Zeilenabstand 6/72" 32DF 0D 00469 lninit DB 0dh,1bh,'K',80h,01h ;Dotgr. einf. D. 32E4 0000 00470 buffer DW 0000h,0000h,0000h ;Puffer f. HRG 32EA 00471 cmdbuf EQU $ ;Puffer für Befehlszeiger 00472 3000 00473 END finit 00000 Fehler ASC 3157 CLS 30A6 HRGadr 3248 HRGoff 30E5 INV 30AE LINE 30D9 LPRINT 30ED PSR 3181 PSRexit 319A argum 31A1 bitlop 3120 buffer 32E4 byte 3208 bytelop 3118 chrtab 3285 clear 30AA clsinv 3084 cmd 3074 cmdbuf 32EA command 302C displc 3239 doublop 31EE exit1 30D7 exit2 3155 fcterr 31AD gosave 327D hello 3038 hexdisp 3166 hlinlop 3112 finit 3000 linelop 3103 lninit 32DF lprint 31FC lsloop 308E msloop 3087 nibble 321F nibloop 3232 out 3198 outa 30CF output 323C point 319D prestor 32D5 reset 3192 restor 3275 savrest 3255 scrnlop 30FF seekchr 3229 set 3196 swaplop 308E vidsav 3253 vidsavl 325A vidsav2 325C |